/*
 * Amkai Enterprise Solution (AES.) 
 * Copyright 2004-2008 by Amkai(TM), Inc.
 * www.amkai.com
 * 
 * Project: webservice
 * Package: com.amkai.aes.webservice.binary.objecthandler.billing
 * File: ChargeImportFromCDMHandler.java
 * Created: 2008.06.11. 11:52:53
 * Author: polaj 
 * 
 */
package com.amkai.aes.webservice.binary.objecthandler.billing;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amkai.aes.aescommon.exceptions.AOException;
import com.amkai.aes.aescommon.inventory.OneToOneHelper;
import com.amkai.aes.aescommon.service.binary.job.billing.ChargeImportJob;
import com.amkai.aes.aescommon.service.result.billing.ChargeImportResult;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.phase.DepartmentLog;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.phase.ExtendedDepartmentLog;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.procedure.ProcedureLog;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.AdjustmentDescriptor;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.ResourceLog;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.SupplyLog;
import com.amkai.aes.generatedbeans.cdmcasehistory.logdetails.resources.TransactionDescriptor;
import com.amkai.aes.generatedbeans.inventory.InventoryElement;
import com.amkai.aes.generatedbeans.inventory.ItemLocation;
import com.amkai.aes.generatedbeans.inventory.VendorOrderInformation;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.procedure.CarrierCodes;
import com.amkai.aes.generatedbeans.registration.OrganizationSpecificProperties;
import com.amkai.aes.generatedbeans.scheduling.AbstractAppointment;
import com.amkai.aes.generatedbeans.scheduling.ResourceConnection;
import com.amkai.aes.generatedbeans.scheduling.ResourceConnectionProperty;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

public class ChargeImportHandler implements JobObjectHandler<ChargeImportJob, Department, ChargeImportResult> {

	private static final Log log = LogFactory.getLog(ChargeImportHandler.class);
	protected static final String TITLE = "Change Import";
	
	@Override
	public ChargeImportResult process(ChargeImportJob job, Department dep) throws Exception {
		
		switch (job.getAction()) {
			case GET_IMPORTABLE_DEPARTMENT_LOGS:	return getImportableDepartmentLogs(job, dep);
			case GET_DEPARTMENT_LOG: return getDepartmentLog(job, dep);
		}
		throw new AOException(TITLE,"Unknown action",job.getAction().name(),null);
	}
	
	protected ChargeImportResult getImportableDepartmentLogs(ChargeImportJob job, Department dep) throws Exception {
		switch (dep.getDepartmentType().getKind()) {
		case ANESTHESIA_PROFESSIONAL:
			return getImportableDepartmentLogsFromAnesthesia(job, dep);
		case SURGERY_CENTER:
		case SURGICAL_HOSPITAL:
			return getImportableDepartmentLogsFromSC(job, dep);
		}
		throw new AOException(TITLE,"Cannot import","Cannot import from "+dep.getName(),null);
	}

	protected ChargeImportResult getImportableDepartmentLogsFromAnesthesia(ChargeImportJob job, Department dep) throws Exception {
		ChargeImportResult result = new ChargeImportResult();
		result.setImportableDepartmentLogs(new ArrayList<DepartmentLog>());
		SessionManager sm = SiteManager.Start();
		try {
			List<Long> l = sm.execute("SELECT DISTINCT pl.anesthesiaDepartmentLog.id " +
					"FROM ProcedureLog pl " +
					"WHERE pl.anesthesiaDepartmentLog.cdmCaseHistory.patient=:patient " +
					"AND pl.anesthesiaDepartmentLog.cdmCaseHistory.pmCase=:pmcase " +
					"AND pl.procedure IS NOT NULL " +
					"AND pl.charge IS NULL")
					.setParameter("patient", job.getPatient())
					.setParameter("pmcase", job.getPmCase())
					.list();
			DepartmentLog dlog = null;
			for (Long id : l) {
				dlog = sm.get(DepartmentLog.class, id);
				if (!result.getImportableDepartmentLogs().contains(dlog)) {
					result.getImportableDepartmentLogs().add(dlog);
				}
			}
			/*
			l = sm.execute("SELECT DISTINCT sl.departmentLog.id " +
					"FROM SupplyLog sl " +
					"WHERE sl.departmentLog.cdmCaseHistory.patient=:patient " +
					"AND sl.departmentLog.cdmCaseHistory.pmCase=:pmcase " +
					"AND sl.supplyResourceItem.billableItem=true " +
					"AND sl.supplyResourceItem IS NOT NULL ")
					.setParameter("patient", job.getPatient())
					.setParameter("pmcase", job.getPmCase())
					.list();
			for (Long id : l) {
				dlog = sm.get(DepartmentLog.class, id);
				if (!result.getImportableDepartmentLogs().contains(dlog))
					result.getImportableDepartmentLogs().add(dlog);
			}
			*/
			for (DepartmentLog dl : result.getImportableDepartmentLogs()) {
				if (dl.getCdmCaseHistory() != null) {
					if (dl.getCdmCaseHistory().getPmCase() != null) {
						if (dl.getCdmCaseHistory().getPmCase().getAbstractAppointment() != null) {
							dl.getCdmCaseHistory().getPmCase().getAbstractAppointment().getFacility().getName();
						}
					}
				}
				if (dl.getPhaseTimeLog() != null) {
					dl.getPhaseTimeLog().getBeginDate();
					dl.getPhaseTimeLog().getBeginTime();
				}
			}
		}
		catch (Exception e) {
			result.setException(e);
		}
		finally {
			sm.closeSession();
		}
		return result;
	}

	protected ChargeImportResult getImportableDepartmentLogsFromSC(ChargeImportJob job, Department dep) throws Exception {
		ChargeImportResult result = new ChargeImportResult();
		result.setImportableDepartmentLogs(new ArrayList<DepartmentLog>());
		SessionManager sm = SiteManager.Start();
		try {
			List<Long> l = sm.execute("SELECT DISTINCT pl.extendedDepartmentLog.id " +
					"FROM ProcedureLog pl " +
					"WHERE pl.extendedDepartmentLog.cdmCaseHistory.patient=:patient " +
//					"AND pl.extendedDepartmentLog.cdmCaseHistory.pmCase=:pmcase " +
					"AND pl.extendedDepartmentLog.abstractAppointment=:aa " +
					"AND pl.procedure IS NOT NULL " +
					"AND pl.charge IS NULL")
					.setParameter("patient", job.getPatient())
//					.setParameter("pmcase", job.getPmCase())
					.setParameter("aa", job.getAbstractAppointment())
					.list();
			DepartmentLog dlog = null;
			for (Long id : l) {
				dlog = sm.get(DepartmentLog.class, id);
				if (!result.getImportableDepartmentLogs().contains(dlog)) {
					result.getImportableDepartmentLogs().add(dlog);
				}
			}
			l = sm.execute("SELECT DISTINCT sl.departmentLog.id " +
					"FROM SupplyLog sl " +
					"WHERE sl.departmentLog.cdmCaseHistory.patient=:patient " +
//					"AND sl.departmentLog.cdmCaseHistory.pmCase=:pmcase " +
					"AND sl.departmentLog.cdmCaseHistory.pmCase.abstractAppointment=:aa " +
					"AND sl.supplyResourceItem.billableItem=true " +
					"AND sl.supplyResourceItem IS NOT NULL ")
					.setParameter("patient", job.getPatient())
//					.setParameter("pmcase", job.getPmCase())
					.setParameter("aa", job.getAbstractAppointment())
					.list();
			for (Long id : l) {
				dlog = sm.get(DepartmentLog.class, id);
				if (!result.getImportableDepartmentLogs().contains(dlog))
					result.getImportableDepartmentLogs().add(dlog);
			}
			
			for (DepartmentLog dl : result.getImportableDepartmentLogs()) {
				if (dl.getCdmCaseHistory() != null) {
					if (dl.getCdmCaseHistory().getPmCase() != null) {
						if (dl.getCdmCaseHistory().getPmCase().getAbstractAppointment() != null) {
							dl.getCdmCaseHistory().getPmCase().getAbstractAppointment().getFacility().getName();
						}
					}
				}
				if (dl.getPhaseTimeLog() != null) {
					dl.getPhaseTimeLog().getBeginDate();
					dl.getPhaseTimeLog().getBeginTime();
				}
			}
		}
		catch (Exception e) {
			result.setException(e);
		}
		finally {
			sm.closeSession();
		}
		return result;
	}	
/*
	protected ChargeImportResult getDepartmentLog(ChargeImportJob job, Department dep) throws Exception {
		switch (dep.getDepartmentType().getKind()) {
		case ANESTHESIA_PROFESSIONAL:
			return getDepartmentLogFromAnesthesia(job, dep);
		case SURGERY_CENTER:
		case SURGICAL_HOSPITAL:
			return getDepartmentLogFromSC(job, dep);
		}
		throw new AOException(TITLE,"Cannot import","Cannot import from "+dep.getName(),null);
	}
*/	
	protected ChargeImportResult getDepartmentLog(ChargeImportJob job, Department dep) throws Exception {
		ChargeImportResult result = new ChargeImportResult();
		SessionManager sm = SiteManager.Start();
		try {
			DepartmentLog dl = job.getDepartmentLog();
			if (dl instanceof ExtendedDepartmentLog) {
				dl = (ExtendedDepartmentLog)sm.execute("FROM ExtendedDepartmentLog edl " +
						"LEFT JOIN FETCH edl.cdmCaseHistory cch " +
						"LEFT JOIN FETCH cch.patient " +
						"LEFT JOIN FETCH cch.patient.person " +
						"LEFT JOIN FETCH edl.abstractAppointment " +
						"LEFT JOIN FETCH cch.pmCase pmcase " +
						"LEFT JOIN FETCH pmcase.cdmCaseHistories " +
						"LEFT JOIN FETCH pmcase.abstractAppointment aa " +
						"LEFT JOIN FETCH pmcase.referringDoctor ref " +
						"LEFT JOIN FETCH aa.facility fac " +
						"LEFT JOIN FETCH aa.appointmentType " +
						"LEFT JOIN FETCH pmcase.primaryPhysician pp " +
						"LEFT JOIN FETCH edl.procedureLogs pl " +
						"LEFT JOIN FETCH pl.procedureLogDiagnosisAssociations diags " +
						"LEFT JOIN FETCH diags.diagnosis diag " +
						"LEFT JOIN FETCH pl.procedure p " +
						"LEFT JOIN FETCH pl.facility " +
						"LEFT JOIN FETCH pl.renderingProvider " +
						"LEFT JOIN FETCH p.cptCode " +
						"LEFT JOIN FETCH pl.sourceOfRevenue " +
						"LEFT JOIN FETCH pl.sourceOfRevenue.journalCodeForWriteOff " +
						"LEFT JOIN FETCH pl.cptModifier1 " +
						"LEFT JOIN FETCH pl.cptModifier1.journalCodeForWriteOff " +
						"LEFT JOIN FETCH pl.cptModifier2 " +
						"LEFT JOIN FETCH pl.cptModifier2.journalCodeForWriteOff " +
						"LEFT JOIN FETCH pl.cptModifier3 " +
						"LEFT JOIN FETCH pl.cptModifier3.journalCodeForWriteOff " +
						"LEFT JOIN FETCH pl.cptModifier4 " +
						"LEFT JOIN FETCH pl.cptModifier4.journalCodeForWriteOff " +
						"LEFT JOIN FETCH p.revenueCode " +
						"LEFT JOIN FETCH pl.icdProcedureCode1 " +
						"LEFT JOIN FETCH pl.icdProcedureCode2 " +
						"LEFT JOIN FETCH pl.icdProcedureCode3 " +
						"LEFT JOIN FETCH edl.resourceLogs rl " +
						"WHERE edl.id=:id ORDER BY pl.sequence ASC")
						.setParameter("id", dl.getId())
						.uniqueResult();
				// KKORNEL: AES-11579
				if ((dl != null) && (dl.getPhaseTimeLog() != null)) {
					dl.getPhaseTimeLog().getBeginDate();
					dl.getPhaseTimeLog().getBeginTime();
					dl.getPhaseTimeLog().getEndDate();
					dl.getPhaseTimeLog().getEndTime();
				}
			}
			else {
				dl = (DepartmentLog)sm.execute("FROM DepartmentLog dl " +
						"LEFT JOIN FETCH dl.cdmCaseHistory cch " +
						"LEFT JOIN FETCH cch.patient " +
						"LEFT JOIN FETCH cch.patient.person " +
						"LEFT JOIN FETCH cch.pmCase pmcase " +
						"LEFT JOIN FETCH pmcase.cdmCaseHistories " +
						"LEFT JOIN FETCH pmcase.referringDoctor ref " +
						"LEFT JOIN FETCH pmcase.abstractAppointment aa " +
						"LEFT JOIN FETCH aa.facility fac " +
						"LEFT JOIN FETCH aa.appointmentType " +
						"LEFT JOIN FETCH pmcase.primaryPhysician pp " +
						"LEFT JOIN FETCH dl.resourceLogs rl " +
						"WHERE dl.id=:id")
						.setParameter("id", dl.getId())
						.uniqueResult();
			}
			if (dl instanceof ExtendedDepartmentLog) {
				ExtendedDepartmentLog edl = (ExtendedDepartmentLog)dl;
				AbstractAppointment aa = dl.getCdmCaseHistory().getPmCase().getAbstractAppointment();
				if (aa != null) {
					for (ResourceConnection rc : aa.getResourceConnections()) {
						for (ResourceConnectionProperty rcp : rc.getResourceConnectionProperty()) {
							rcp.getId();
						}
						rc.getReservation().getBeginTime();
					}
				}
				for (ProcedureLog plog : edl.getProcedureLogs()) {
					for (CarrierCodes cc : plog.getProcedure().getCarrierCodes()) {
						if (cc.getCptCode() != null)
							cc.getCptCode().getName();
						if (cc.getCptModifier1() != null) {
							if (cc.getCptModifier1().getJournalCodeForWriteOff() != null)
								cc.getCptModifier1().getJournalCodeForWriteOff().getName();
						}
						if (cc.getCptModifier2() != null) {
							if (cc.getCptModifier2().getJournalCodeForWriteOff() != null)
								cc.getCptModifier2().getJournalCodeForWriteOff().getName();
						}
						if (cc.getCptModifier3() != null) {
							if (cc.getCptModifier3().getJournalCodeForWriteOff() != null)
								cc.getCptModifier3().getJournalCodeForWriteOff().getName();
						}
						if (cc.getCptModifier4() != null) {
							if (cc.getCptModifier4().getJournalCodeForWriteOff() != null)
								cc.getCptModifier4().getJournalCodeForWriteOff().getName();
						}
						if (cc.getRevenueCode() != null)
							cc.getRevenueCode().getName();
						if (cc.getAdditionalReveneuCode() != null)
							cc.getAdditionalReveneuCode().getName();
					}
				}
			}
			for (OrganizationSpecificProperties osp : dl.getCdmCaseHistory().getPatient().getOrganizationSpecificPropertieses()) {
				osp.getPatient().getAccount().getAccountNumber();
				osp.getBaseOrganization().getName();
			}
			for (ResourceLog rl : dl.getResourceLogs()) {
				if (rl.getCdmCaseHistory() != null) {
					if (rl.getCdmCaseHistory().getPmCase() != null) {
						rl.getCdmCaseHistory().getPmCase().getName();
						if (rl.getCdmCaseHistory().getPmCase().getPrimaryPhysician() != null) {
							rl.getCdmCaseHistory().getPmCase().getPrimaryPhysician().getName();
						}
					}
				}
				if (rl instanceof SupplyLog) {
					SupplyLog sl = (SupplyLog)rl;
					if (sl.getSupplyResourceItem() != null) {
						if (sl.getSupplyResourceItem().getSourceOfRevenue() != null) {
							sl.getSupplyResourceItem().getSourceOfRevenue().getName();
						}
						if (sl.getSupplyResourceItem().getInventoryElement() != null) {
							InventoryElement ie = OneToOneHelper.getInverseInstance(InventoryElement.class, sl.getSupplyResourceItem().getInventoryElement());
							for (VendorOrderInformation vo : ie.getVendorOrderInformations()) {
								vo.getPricePerUsageUnit();
							}
						}
						if (sl.getSupplyResourceItem().getCptCode() != null)
							sl.getSupplyResourceItem().getCptCode().getName();
					}
					//AES-15781
					//for (Charge charge : sl.getCharges()) {
					//	charge.getId();
					//}
					//FIXME : 3.6 Changes
					/*
					for (ChargeCdmSupplyLogAssociation assoc : sl.getChargeCdmSupplyLogAssociations()) {
						assoc.getCharge().getId();
					}
					*/
					if (sl.getAdjustmentDescriptors() != null) {
						for (AdjustmentDescriptor ad : sl.getAdjustmentDescriptors()){
							//AES-9468
							for(ItemLocation itemLocation : ad.getInventoryElement().getItemLocations()){
								if(itemLocation.getLocation() != null){
									itemLocation.getLocation().getName();
								}								
							}
							//--
							for(TransactionDescriptor transactionDescriptor : ad.getTransactionDescriptors()){
								transactionDescriptor.getQuantity();
							}
						}
					}
				}
			}
			result.setDepartmentLog(dl);
		}
		catch (Exception e) {
			result.setException(e);
		}
		finally {
			sm.closeSession();
		}
		return result;
	}
}
